package org.star.dolphin.service;

import lombok.extern.slf4j.Slf4j;
import org.star.dolphin.domain.ResponseMessage;
import org.star.dolphin.factory.ResponseMessageFactory;
import org.star.dolphin.utils.SpringUtil;
import org.star.dolphin.utils.StringUtil;
import tk.mybatis.mapper.common.Mapper;

import java.lang.reflect.ParameterizedType;
import java.util.List;

@Slf4j
public abstract class BaseService<T> {

    private static final String MAPPER = "Mapper";

    /**
     * service mapper
     *
     * @return
     */
    //public abstract Mapper<T> mapper();

    //使用spring 上下文自动获取mapper对象

    /**
     * 自动装入对象包装
     * 如果需要使用特殊的对象包装即在之类重新该方法
     *
     * @return
     */
    public Mapper<T> mapper() {

        String targetName = null;

        try {
            ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
            Class target = (Class<T>) pt.getActualTypeArguments()[0];
            String simpleName = target.getSimpleName();
            targetName = StringUtil.captureName(simpleName) + MAPPER;
            return (Mapper) SpringUtil.getBean(targetName);
        } catch (Exception e) {
            log.error("不被认可的对象包装：" + targetName);
            log.error(e.getMessage());
            return null;
        }
    }

    /**
     * 批量删除
     *
     * @param entity
     * @return
     */
    public ResponseMessage<String> batchDelete(List<T> entity) {
        Boolean delAll = true;

        for (T item : entity) {
            ResponseMessage res = deleteEntity(item);
            if (res.hasError()) {
                delAll = false;
            }
        }

        if (delAll) {
            return ResponseMessageFactory.success();
        } else {
            return ResponseMessageFactory.error("部分删除成功！");
        }
    }

    /**
     * 保存一个实体，null的属性不会保存，会使用数据库默认值
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> createEntitySelective(T entity) {
        ResponseMessage<T> res = this.validateCreate(entity);
        if (res.hasError()) {
            return res;
        }

        this.fillEntity(entity);

        res = this.beforeCreate(entity);
        if (res.hasError()) {
            return res;
        }

        Integer result = this.mapper().insertSelective(entity);
        if (result > 0) {
            res = ResponseMessageFactory.success(entity);
        } else {
            res = ResponseMessageFactory.error();
            return res;
        }

        res = this.afterCreate(entity);

        return res;
    }

    /**
     * 保存一个实体，null的属性也会保存，不会使用数据库默认值
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> createEntity(T entity) {
        ResponseMessage<T> res = this.validateCreate(entity);
        if (res.hasError()) {
            return res;
        }

        this.fillEntity(entity);

        res = this.beforeCreate(entity);
        if (res.hasError()) {
            return res;
        }

        Integer result = this.mapper().insert(entity);
        if (result > 0) {
            res = ResponseMessageFactory.success(entity);
        } else {
            res = ResponseMessageFactory.error();
            return res;
        }

        res = this.afterCreate(entity);

        return res;
    }

    /**
     * 根据主键更新属性不为null的值
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> updateEntity(T entity) {
        ResponseMessage<T> res = this.validateUpdate(entity);
        if (res.hasError()) {
            return res;
        }

        res = this.beforeUpdate(entity);
        if (res.hasError()) {
            return res;
        }

        this.fillUpdateEntity(entity);

        Integer result = this.mapper().updateByPrimaryKeySelective(entity);
        if (result > 0) {
            res = ResponseMessageFactory.success(entity);
        } else {
            res = ResponseMessageFactory.error();
            return res;
        }

        res = this.afterUpdate(entity);
        return res;
    }

    /**
     * 根据主键更新实体全部字段，null值会被更新
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> updateEntityByPrimary(T entity) {
        ResponseMessage<T> res = this.validateUpdate(entity);
        if (res.hasError()) {
            return res;
        }

        res = this.beforeUpdate(entity);
        if (res.hasError()) {
            return res;
        }

        this.fillUpdateEntity(entity);

        Integer result = this.mapper().updateByPrimaryKey(entity);
        if (result > 0) {
            res = ResponseMessageFactory.success(entity);
        } else {
            res = ResponseMessageFactory.error();
            return res;
        }

        res = this.afterUpdate(entity);
        return res;
    }

    /**
     * 根据主键字段进行删除，方法参数必须包含完整的主键属性
     *
     * @param key
     * @return
     */
    public ResponseMessage<T> deleteEntityByPrimary(Object key) {

        T entity = getEntityByPrimary(key);

        ResponseMessage<T> res = this.validateUpdate(entity);
        if (res.hasError()) {
            return res;
        }

        res = this.beforeUpdate(entity);
        if (res.hasError()) {
            return res;
        }

        Integer result = this.mapper().deleteByPrimaryKey(key);
        if (result <= 0) {
            return ResponseMessageFactory.error();
        }

        res = this.afterUpdate(entity);
        return res;
    }

    /**
     * 根据实体属性作为条件进行删除，查询条件使用等号
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> deleteEntity(T entity) {
        ResponseMessage<T> res = this.validateDelete(entity);
        if (res.hasError()) {
            return res;
        }

        res = this.beforeDelete(entity);
        if (res.hasError()) {
            return res;
        }

        Integer result = this.mapper().delete(entity);
        if (result > 0) {
            res = ResponseMessageFactory.success(entity);
        } else {
            res = ResponseMessageFactory.error();
            return res;
        }

        res = this.afterDelete(entity);
        return res;
    }

    /**
     * 根据Condition条件删除数据
     * 未调用AOP方法
     *
     * @param condition
     * @return
     */
    public ResponseMessage<T> deleteEntityByCondition(Object condition) {
        ResponseMessage<T> res;
        Integer result = this.mapper().deleteByExample(condition);
        if (result > 0) {
            res = ResponseMessageFactory.success();
        } else {
            res = ResponseMessageFactory.error();
            return res;
        }
        return res;
    }

    /**
     * 根据实体中的属性值进行查询，查询条件使用等号
     *
     * @param entity
     * @return
     */
    public List<T> findEntity(T entity) {
        return this.mapper().select(entity);
    }

    /**
     * 根据条件查询数据
     *
     * @param condition
     * @return
     */
    public List<T> findEntityByCondition(Object condition) {
        return this.mapper().selectByExample(condition);
    }

    /**
     * 查询全部结果，select(null)方法能达到同样的效果
     *
     * @return
     */
    public List<T> selectAll() {
        return this.mapper().selectAll();
    }

    /**
     * 根据实体中的属性查询总数，查询条件使用等号
     *
     * @param entity
     * @return
     */
    public Integer selectCount(T entity) {
        return this.mapper().selectCount(entity);
    }

    /**
     * 根据条件查询总数
     *
     * @param condition
     * @return
     */
    public Integer selectCountByCondition(Object condition) {
        return this.mapper().selectCountByExample(condition);
    }

    /**
     * 根据实体中的属性进行查询，只能有一个返回值，有多个结果是抛出异常，查询条件使用等号
     *
     * @param entity
     * @return
     */
    public T getEntity(T entity) {
        return (T) this.mapper().selectOne(entity);
    }

    /**
     * 根据主键字段进行查询，方法参数必须包含完整的主键属性，查询条件使用等号
     *
     * @param key
     * @return
     */
    public T getEntityByPrimary(Object key) {
        return (T) this.mapper().selectByPrimaryKey(key);
    }

    /**
     * 创建校验
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> validateCreate(T entity) {
        return ResponseMessageFactory.success(entity);
    }

    /**
     * 填充
     *
     * @param entity
     */
    public void fillEntity(T entity) {
    }

    /**
     * 修改填充
     *
     * @param entity
     */
    public void fillUpdateEntity(T entity) {

    }

    /**
     * 创建之前
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> beforeCreate(T entity) {
        return ResponseMessageFactory.success(entity);
    }

    /**
     * 创建之后
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> afterCreate(T entity) {
        return ResponseMessageFactory.success(entity);
    }

    /**
     * 校验
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> validateUpdate(T entity) {
        return ResponseMessageFactory.success(entity);
    }

    /**
     * 之前
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> beforeUpdate(T entity) {
        return ResponseMessageFactory.success(entity);
    }

    /**
     * 之后
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> afterUpdate(T entity) {
        return ResponseMessageFactory.success(entity);
    }

    /**
     * 校验
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> validateDelete(T entity) {
        return ResponseMessageFactory.success(entity);
    }

    /**
     * 之前
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> beforeDelete(T entity) {
        return ResponseMessageFactory.success(entity);
    }

    /**
     * 之后
     *
     * @param entity
     * @return
     */
    public ResponseMessage<T> afterDelete(T entity) {
        return ResponseMessageFactory.success(entity);
    }

}
